//FAS低代码开发平台
//变更日志插件: 针对CUD操作记录变更日志，其中新增、修改的克隆TRecord逻辑是避免状态机插件【保存后事件】影响返给前端的TRecord内容
//新增：
//    1、前端NewTRecord A传入后【BeforeExecuteSQL】做初次变更比较（没有OldValue），为A生成ChangeSet供状态机【保存前事件】Action脚本使用
//    2、数据落盘后【Finish】，从DB中取出最新NewTRecord B（获取DB默认值），克隆NewTRecord C，将B传入插件，再次做变更比较。
//       此时生成的变更为包含状态机脚本更新后的最新变更，直接生成大数据日志，而后执行状态机的【保存后事件】
//    3、将C返回给前端。
//修改：
//    1、前端NewTRecord A传入后【BeforeExecuteSQL】，获取DB中的OldRecord，做变更比较，将NewTRecord A,OldValue传入供状态机【保存前事件】Action脚本使用
//    2、状态机【保存前事件】执行完毕后（A的ChangeSet已包含最新变更），克隆NewTRecord B，
//       数据落盘后【Finish】，将A传入变更日志插件中，直接生成大数据日志。而后执行状态机的【保存后事件】
//    3、将最新的时间戳赋值给B后返回前端。
//删除：
//    1、由于删除不走状态机逻辑，故在【BeforeExecuteSQL】时，变更日志插件中生成TRecord实例，只记录主键id变更，放到上下文中
//    2、数据落盘后【Finish】，在上下文中拿到生成的TRecord实例，生成大数据日志
//    3、删除不向前端返回数据
//===============================================================================
//变更历史纪录
//日期			版本	修改人	描述
//===============================================================================

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.DataAccess.Engine
{

    /// <summary>
    /// TRecord比较类，主键列内容相等，认定为同一单据
    /// </summary>
    public class TRecordPKComparer : IEqualityComparer<TRecord>
    {
        public bool Equals(TRecord x, TRecord y)
        {
            bool pkflag = string.Equals(x.PKColumnName, y.PKColumnName);
            var strVal1 = x.GetValue(x.PKColumnName)?.ToString();
            var strVal2 = y.GetValue(y.PKColumnName)?.ToString();
            if (!pkflag) return false;
            if (int.TryParse(strVal1, out int intVal1) && int.TryParse(strVal2, out int intVal2))
            {
                return intVal1 == intVal2;
            }
            else
            {
                return string.Equals(strVal1, strVal2);
            }
        }

        public int GetHashCode(TRecord obj)
        {
            if (obj != null && obj.PKColumnName == null)
            {
                var json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                throw new Exception(string.Format(CommonStringClassEngine.TRecordPKComparer_GetHashCode,json));
            }
            return obj.PKColumnName.GetHashCode();
        }
    }
}
